<?php
/*
 * @Author: lokei
 * @Date: 2022-08-18 21:15:24
 * @LastEditors: lokei
 * @LastEditTime: 2023-07-18 08:32:33
 * @Description: 
 */

namespace App\Http\Controllers\Pay\Weixin;

use App\Http\Controllers\Controller;
use App\Models\Pay\ConfModel;
use App\Models\Pay\Record\PayRecordModel;
use App\Models\Store\StoreModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Formatter;

class NotifyController extends Controller
{
    public function callback($pid, $store_id, Request $request)
    {
        $inWechatpaySignature = $request->header('Wechatpay-Signature'); // 请根据实际情况获取
        $inWechatpayTimestamp = $request->header('Wechatpay-Timestamp'); // 请根据实际情况获取
        $inWechatpaySerial = $request->header('Wechatpay-Serial'); // 请根据实际情况获取
        $inWechatpayNonce = $request->header('Wechatpay-Nonce'); // 请根据实际情况获取
        $inBody = file_get_contents('php://input'); // 请根据实际情况获取，例如: file_get_contents('php://input');

        if ($store_id > 0) {
            $conf = StoreModel::where('id', '=', $store_id)->first();
        } else {
            $conf = ConfModel::first();
        }
        $apiv3Key = $conf->signkey; // 在商户平台上设置的APIv3密钥

        // 根据通知的平台证书序列号，查询本地平台证书文件，
        // 假定为 `/path/to/wechatpay/inWechatpaySerial.pem`
        if ($pid != null && $pid != '' && $pid != '0') {
            $platformPublicKeyInstance = Rsa::from('file://' . env('ATTACHMENT_ROOT') . $pid . '/' . 'wxpay/' . 'wechatpay_' . $inWechatpaySerial . '.pem', Rsa::KEY_TYPE_PUBLIC);
        } else {
            $platformPublicKeyInstance = Rsa::from('file://' . env('ATTACHMENT_ROOT') . 'wxpay/' . 'wechatpay_' . $inWechatpaySerial . '.pem', Rsa::KEY_TYPE_PUBLIC);
        }

        // 检查通知时间偏移量，允许5分钟之内的偏移
        $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
        $verifiedStatus = Rsa::verify(
            // 构造验签名串
            Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
            $inWechatpaySignature,
            $platformPublicKeyInstance
        );
        if ($timeOffsetStatus && $verifiedStatus) {
            // 转换通知的JSON文本消息为PHP Array数组
            $inBodyArray = (array)json_decode($inBody, true);
            // 使用PHP7的数据解构语法，从Array中解构并赋值变量
            ['resource' => [
                'ciphertext'      => $ciphertext,
                'nonce'           => $nonce,
                'associated_data' => $aad
            ]] = $inBodyArray;
            // 加密文本消息解密
            $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
            // 把解密后的文本转换为PHP Array数组
            $inBodyResourceArray = (array)json_decode($inBodyResource, true);
            $fields = array();
            $fields['sn'] = $inBodyResourceArray['out_trade_no'];
            if ($pid != null && $pid != '') {
                $fields['pid'] = $pid;
            }
            Redis::xAdd('pay_success', '*', $fields);

            $pay_record = PayRecordModel::where('tid', '=', $inBodyResourceArray['out_trade_no'])->first();
            $pay_record->transaction_id = $inBodyResourceArray['transaction_id'];
            $pay_record->status = '1';
            $pay_record->save();
        }

        echo 'success';

        fastcgi_finish_request();

        if (isset($pay_record) && $pay_record->store_id > 0) {
            $store = StoreModel::where('id', '=', $pay_record->store_id)->first();
            if ($store->profitsharing_on == '1' && $store->main_mchid_share > 0) {
                $instance = Init::getInstance($pay_record->store_id);
                $main_mch_conf = ConfModel::first();
                $certs_array = json_decode($store->wxpay_platform_certs);
                $cert_serial_no = '';
                foreach ($certs_array as $cert_info) {
                    $cert_serial_no = $cert_info->serial_no;
                    $platformCertificateFilePath = 'file://' . env('ATTACHMENT_ROOT') . 'wxpay/' . 'wechatpay_' . $cert_info->serial_no . '.pem';
                    if (config('app.proj_identity') != null && config('app.proj_identity') != '') {
                        $platformCertificateFilePath = 'file://' . env('ATTACHMENT_ROOT') . config('app.proj_identity') . '/' . 'wxpay/' . 'wechatpay_' . $cert_info->serial_no . '.pem';
                    }
                    $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
                }
                $encryptor = static function (string $msg) use ($platformPublicKeyInstance): string {
                    return Rsa::encrypt($msg, $platformPublicKeyInstance);
                };
                sleep(60);
                $instance
                    ->v3->profitsharing->orders
                    ->post([
                        'json' => [
                            'appid'        => config('app.appid'),
                            'transaction_id' => $inBodyResourceArray['transaction_id'],
                            'out_order_no' => $inBodyResourceArray['out_trade_no'],
                            'receivers'        => [[
                                'type' => 'MERCHANT_ID',
                                'account' => $main_mch_conf->mchid,
                                'name' => $encryptor($main_mch_conf->mch_name),
                                'amount' => intval($inBodyResourceArray['amount']['total'] * $store->main_mchid_share / 100),
                                'description' => '分账给' . $main_mch_conf->mchid,
                                'unfreeze_unsplit' => true
                            ]],
                            'unfreeze_unsplit' => true
                        ],
                        'headers' => [
                            'Wechatpay-Serial' => $cert_serial_no
                        ]
                    ]);
            }
        }
    }
}
